package com.amtf.datafile2.core.txt;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.amtf.datafile2.DataException;
import com.amtf.datafile2.DataRecord;
import com.amtf.datafile2.cfg.txt.TxtDataFieldDefinition;
import com.amtf.datafile2.cfg.txt.TxtDataTableDefinition;
import com.amtf.datafile2.cfg.txt.TxtDataTableDefinition.PARSE_MODE;
import com.amtf.datafile2.core.std.StdTxtDataTable;

public class TxtDataTable extends StdTxtDataTable<TxtDataTableDefinition, TxtDataFieldDefinition> {

	// public TxtDataTable(String name, File file, ACCESS_TYPE accessType, String charsetName) throws IOException {
	// super(name, file, accessType, charsetName);
	// this.definition = TxtDataRecordDefinitionStore.DEFAULT_CSV_DEFINITION;
	// }

	// public TxtDataTable(String name, File file, ACCESS_TYPE accessType, String charsetName, TxtDataRecordDefinition definition) throws DataException {
	// super(name, definition, file, accessType, charsetName);
	// this.definition = definition;
	// }

	public TxtDataTable(String name, File file, String charsetName, TxtDataTableDefinition definition) throws DataException {
		super(name, definition, file, charsetName);
		this.definition = definition;
	}

	// public TxtDataTable(String name, BufferedReader bufferedReader, OutputStreamWriter streamWriter) {
	// super(name, bufferedReader, streamWriter);
	// definition = TxtDataRecordDefinitionStore.DEFAULT_CSV_DEFINITION;
	// }
	//
	// public TxtDataTable(String name, BufferedReader bufferedReader) {
	// super(name, bufferedReader);
	// definition = TxtDataRecordDefinitionStore.DEFAULT_CSV_DEFINITION;
	// }
	//
	// public TxtDataTable(String name, OutputStreamWriter streamWriter) {
	// super(name, streamWriter);
	// definition = TxtDataRecordDefinitionStore.DEFAULT_CSV_DEFINITION;
	// }

	// public TxtDataTable(String name, BufferedReader bufferedReader, OutputStreamWriter streamWriter, TxtDataRecordDefinition definition) {
	// this(name, bufferedReader, streamWriter);
	// this.definition = definition;
	// }
	//
	// public TxtDataTable(String name, BufferedReader bufferedReader, TxtDataRecordDefinition definition) {
	// this(name, bufferedReader);
	// this.definition = definition;
	// }
	//
	// public TxtDataTable(String name, OutputStreamWriter streamWriter, TxtDataRecordDefinition definition) {
	// this(name, streamWriter);
	// this.definition = definition;
	// }

	@Override
	public DataRecord readFirstLine() throws IOException, DataException {
		if (definition.isFirstRowTitle()) {
			DataRecord title = super.readFirstLine();
			if (title != null) {
				if (definition.getParseMode() == PARSE_MODE.INTERSECTIONS_PRIORITY) {
					List<String> existFields = new ArrayList<String>();

					String[] titleNames = title.getValues();
					for (String titleName : titleNames) {
						if (titleName != null && titleName.trim().length() != 0) {
							titleName = titleName.trim();
							if (definition.getField(titleName) == null) {
								// definition.addFieldDefinition(titleName);
								throw new DataException("Column title [" + titleName + "] not found in definition");
							}

							existFields.add(titleName.toUpperCase());
						}
					}

					List<String> tobeRemove = new ArrayList<String>();
					List<TxtDataFieldDefinition> defFields = definition.getFields();
					for (TxtDataFieldDefinition defField : defFields) {
						if (!existFields.contains(defField.getName().toUpperCase())) {
							tobeRemove.add(defField.getName());
						}
					}
					for (String titleName : tobeRemove) {
						definition.removeField(titleName);
					}
				}

				if (definition.isTitleAsColumnName()) {
					List<TxtDataFieldDefinition> fielddefs = definition.getFields();
					for (int i = 0; i < fielddefs.size(); i++) {
						TxtDataFieldDefinition fielddef = fielddefs.get(i);
						fielddef.setName(title.getValue(i));
					}
				}

				return super.readNextLine();
			}

			return null;
		} else {
			return super.readFirstLine();
		}
	}

	@Override
	public List<DataRecord> readFirstLines(int readCount) throws IOException, DataException {
		if (definition.isFirstRowTitle()) {
			super.readFirstLine();
		}

		return super.readFirstLines(readCount);
	}

	@Override
	protected DataRecord convertLine(String readLine) throws DataException {
		return TxtDataRecord.parseRecord(definition, readLine);
	}

	@Override
	protected DataRecord convertLine(DataRecord row) {
		return TxtDataRecord.copyValues(definition, row);
	}

	public void writeLine(String[] line) throws IOException, DataException {
		streamWriter.write(TxtDataRecord.parseRecord(definition, line) + CRLF);
		currentWritenLine++;
	}

	public void writeLine(Object[] line) throws IOException, DataException {
		streamWriter.write(TxtDataRecord.parseRecord(definition, line) + CRLF);
		currentWritenLine++;
	}

}
